package com.damai.xml;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.citywithincity.api.ApiBuildConfig;
import com.citywithincity.utils.HttpUtil;
import com.citywithincity.utils.IoUtil;
import com.citywithincity.utils.PathUtil;

public class XMLUtil {

	
	
	
	public static Map<String, String> parseXML(InputStream is, boolean isTree) throws XMLParseException, IOException {
		return parseXML(is, isTree, HttpUtil.DEFAULT_ENCODING);
	}

	
	public static Map<String, String> parseXML(String src) throws IOException, XMLParseException{
		ByteArrayInputStream inputStream =null;
		try{
			inputStream = new ByteArrayInputStream(src.getBytes());
			return parseXML(inputStream,false);
		}finally{
			IoUtil.close(inputStream);
		}
		
		
		
	}
	
	/**
	 * 
	 * @param is
	 * @param isTree
	 * @param encoding
	 * @return
	 * @throws ParserConfigurationException
	 * @throws SAXException
	 * @throws IOException
	 */
	public static Map<String, String> parseXML(InputStream is, boolean isTree, String encoding)
			throws XMLParseException, IOException {
		try {
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			DocumentBuilder db = dbf.newDocumentBuilder();
			Document document = db.parse(is, encoding);
			Map<String, String> map = null;
			if (isTree) {
				map = new TreeMap<String, String>();
			} else {
				map = new HashMap<String, String>();
			}
			NodeList nodes = document.getChildNodes().item(0).getChildNodes();
			for (int i = 0, count = nodes.getLength(); i < count; i++) {
				Node node = nodes.item(i);
				if (node instanceof Element) {
					map.put(node.getNodeName(), node.getTextContent());
				}
			}
			return map;
		} catch (ParserConfigurationException e) {
			throw new XMLParseException(e);
		} catch (SAXException e) {
			throw new XMLParseException(e);
		}

	}

	public static void loadXmlLevel1(String name, XMLVisitor visitor) throws IOException {
		InputStream is = null;
		try {
			is = PathUtil.getConfigInputStream(XMLUtil.class, name);
			parseXMLLevel1(is, visitor);
		} catch (XMLParseException e) {
			throw new IOException(e);
		} finally {
			IoUtil.close(is);
		}
	}

	public static void loadXmlLevel1(Class<?> clazz, String name, XMLVisitor visitor) throws IOException {
		InputStream is = null;
		try {
			is = PathUtil.getConfigInputStream(clazz, name);
			parseXMLLevel1(is, visitor);
		} catch (XMLParseException e) {
			throw new IOException(e);
		} finally {
			IoUtil.close(is);
		}
	}

	public static void parseXMLLevel1(InputStream is, XMLVisitor visitor) throws XMLParseException, IOException {

		try {
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			DocumentBuilder db = dbf.newDocumentBuilder();
			Document document = db.parse(is, ApiBuildConfig.DEFAULT_ENCODING);
			NodeList nodes = document.getChildNodes().item(0).getChildNodes();
			for (int i = 0, count = nodes.getLength(); i < count; i++) {
				Node node = nodes.item(i);
				if (node instanceof Element) {
					Element element = (Element) node;
					visitor.onVisit(element);
				}
			}
		} catch (ParserConfigurationException e) {
			throw new XMLParseException(e);
		} catch (SAXException e) {
			throw new XMLParseException(e);
		}

	}

	public static List<Element> getChildNodes(InputStream is) throws IOException, XMLParseException {
		try {
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			DocumentBuilder db = dbf.newDocumentBuilder();
			Document document = db.parse(is, ApiBuildConfig.DEFAULT_ENCODING);
			NodeList nodes = document.getChildNodes().item(0).getChildNodes();
			List<Element> list = new ArrayList<Element>(nodes.getLength());
			for (int i = 0, count = nodes.getLength(); i < count; i++) {
				Node node = nodes.item(i);
				if (node instanceof Element) {
					list.add((Element) node);
				}
			}
			return list;
		} catch (ParserConfigurationException e) {
			throw new XMLParseException(e);
		} catch (SAXException e) {
			throw new XMLParseException(e);
		}

	}

	/**
	 * 
	 * @param element
	 * @return
	 */
	public static List<Element> getChildNodes(Element element) {
		NodeList nodes = element.getChildNodes();
		List<Element> list = new ArrayList<Element>(nodes.getLength());
		for (int i = 0, count = nodes.getLength(); i < count; i++) {
			Node node = nodes.item(i);
			if (node instanceof Element) {
				list.add((Element) node);
			}
		}
		return list;
	}

	public static void toXMLString(StringBuilder sb, Map<String, Object> data) {
		for (Entry<String, Object> entry : data.entrySet()) {
			String key = entry.getKey();
			Object value = entry.getValue();
			if (value == null) {
				value = "";
			}
			sb.append('<').append(key).append('>').append(value).append("</").append(key).append(">");
		}

	}

	public static Map<String, Object> getMap(Node element) {
		Map<String, Object> data = new LinkedHashMap<String, Object>();
		NodeList nodes = element.getChildNodes();
		for (int i = 0, count = nodes.getLength(); i < count; i++) {
			Node node = nodes.item(i);
			data.put(node.getNodeName(), node.getTextContent());
		}
		return data;
	}

}
